<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 *
 * PHP version 5
 *
 * Copyright 2008 The Picnic PHP Framework
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *            http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @category            Framework
 * @package             Pfw
 * @author              Sean Sitter <sean@picnicphp.com>
 * @copyright           2008 The Picnic PHP Framework
 * @license             http://www.apache.org/licenses/LICENSE-2.0
 * @link                http://www.picnicphp.com
 * @since               0.10
 */

require('../../Pfw/UnitTest/PHPUnit/FwkTestCase.php');
Pfw_Loader::loadClass('Pfw_Paginator_QueryObject');

class Pfw_Paginator_QueryObject_Test extends Pfw_UnitTest_PHPUnit_FwkTestCase
{
    public function setup()
    {
        parent::setup();
        $this->createTableAndData();
    }

    public function  tearDown()
    {
        parent::tearDown();
        $this->dropTable();
    }

    public function testPaginate()
    {
        $qo = Widget::Q();

        $paginator = new Pfw_Paginator_QueryObject($qo, 2, 10);
        $rs = $paginator->paginate();
        $this->assertEquals(10, count($rs));
        $this->assertEquals(11, $paginator->getLastPageNum());
        $this->assertEquals(110, $paginator->getTotal());
        $this->assertEquals($rs[0]->name, "widgetname10");
    }

    public function testHasManyImmediateException()
    {
        $qo = Widget::Q();
        $qo->with('things');

        $pe = null;
        try {
            $paginator = new Pfw_Paginator_QueryObject($qo, 2, 10);
            $rs = $paginator->paginate();
        }
        catch(Exception $e) {
            $pe = $e;
        }
        $this->assertNotEquals($pe, null);
        $this->assertTrue(is_a($pe, "Pfw_Exception_Model"));
    }

    /**
     * This is a thing of beauty
     */
    public function testHasManyPostQuery()
    {
        $qo = Widget::Q();
        $qo->with('things', array('join_strategy' => 'Pfw_Associate_PostQuery'));
        $paginator = new Pfw_Paginator_QueryObject($qo, 2, 10);
        $rs = $paginator->paginate();
        $this->assertEquals(count($rs), 10);
        $this->assertEquals(count($rs[9]->things), 2);
        $this->assertEquals($rs[9]->name, "widgetname19");
        $this->assertEquals($rs[9]->things[0]->name, "thingname-19a");
        $this->assertEquals($rs[9]->things[1]->name, "thingname-19b");
    }

    public function testHasOneImmediate()
    {
        $qo = Widget::Q();
        $qo->with('component');
        $paginator = new Pfw_Paginator_QueryObject($qo, 5, 5);
        $rs = $paginator->paginate();
        $w = end($rs);
        $this->assertEquals($w->name, "widgetname24");
        $this->assertEquals($w->component->name, "componentname24");
        $this->assertEquals(count($rs), 5);
    }

    public function testHasOnePostQuery()
    {
        $qo = Widget::Q();
        $qo->with('component', array('join_strategy' => 'Pfw_Associate_PostQuery'));
        $paginator = new Pfw_Paginator_QueryObject($qo, 5, 5);
        $rs = $paginator->paginate();
        $w = end($rs);
        $this->assertEquals($w->name, "widgetname24");
        $this->assertEquals($w->component->name, "componentname24");
        $this->assertEquals(count($rs), 5);
    }

    public function testBelongsToImmediate()
    {
        $qo = Component::Q();
        $qo->with('widget');
        $paginator = new Pfw_Paginator_QueryObject($qo, 5, 5);
        $rs = $paginator->paginate();
        $c = end($rs);
        $this->assertEquals($c->name, "componentname24");
        $this->assertEquals($c->widget->name, "widgetname24");
        $this->assertEquals(count($rs), 5);
    }
    
    public function testBelongsToPostQuery()
    {
        $qo = Component::Q();
        $qo->with('widget', array('join_strategy' => 'Pfw_Associate_PostQuery'));
        $paginator = new Pfw_Paginator_QueryObject($qo, 5, 5);
        $rs = $paginator->paginate();
        $c = end($rs);
        $this->assertEquals($c->name, "componentname24");
        $this->assertEquals($c->widget->name, "widgetname24");
        $this->assertEquals(count($rs), 5);
    }


    public function createTableAndData()
    {
        $db = Pfw_Db::factory();
        $db->insert("
CREATE TABLE IF NOT EXISTS `widgets` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1");

        $data = array();
        for ($i = 0; $i < 110; $i++) {
            array_push($data, array(
                'name' => "widgetname{$i}",
            ));
        }
        $db->insertAllIntoTable('widgets', $data);

        $db->insert("
CREATE TABLE IF NOT EXISTS `components` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `widget_id` int(11) UNSIGNED NOT NULL,
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1");

        $data = array();
        for ($i = 0; $i < 110; $i++) {
            array_push($data, array(
                'widget_id' => $i + 1,
                'name' => "componentname{$i}",
            ));
        }
        $db->insertAllIntoTable('components', $data);

        $db->insert("
CREATE TABLE IF NOT EXISTS `things` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `widget_id` int(11) UNSIGNED NOT NULL,
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1");

        $data = array();
        $j = 0;
        for ($i = 0; $i < 110; $i++) {
            array_push($data, array(
                'widget_id' => $i + 1,
                'name' => "thingname-{$i}a",
            ));
            array_push($data, array(
                'widget_id' => $i + 1,
                'name' => "thingname-{$i}b",
            ));
        }
        $db->insertAllIntoTable('things', $data);
    }

    public function dropTable()
    {
        $db = Pfw_Db::factory();
        $db->insert("DROP TABLE IF EXISTS `widgets`");
        $db->insert("DROP TABLE IF EXISTS `components`");
        $db->insert("DROP TABLE IF EXISTS `things`");
    }
}

/**
 * Widget test model
 */
class Widget extends Pfw_Model {
    protected static $_query_object;

    public function setup()
    {
        $this->setTable('widgets');
        $this->hasMany('things', array('default_strategy' => 'Immediate'));
        $this->hasOne('component', array('default_strategy' => 'Immediate'));
    }

    public static function Q($db = null)
    {
        $qo = __CLASS__."_QueryObject";
        return new $qo(__CLASS__, $db);
    }
}

class Widget_QueryObject extends Pfw_Model_QueryObject {}

/**
 * Component test model
 */
class Component extends Pfw_Model {
    protected static $_query_object;

    public function setup()
    {
        $this->belongsTo('widget');
    }

    public static function Q($db = null)
    {
        $qo = __CLASS__."_QueryObject";
        return new $qo(__CLASS__, $db);
    }
}

class Component_QueryObject extends Pfw_Model_QueryObject {}

/**
 * Thing test model
 */
class Thing extends Pfw_Model {
    protected static $_query_object;

    public function setup(){}

    public static function Q($db = null)
    {
        $qo = __CLASS__."_QueryObject";
        return new $qo(__CLASS__, $db);
    }
}

class Thing_QueryObject extends Pfw_Model_QueryObject {}

?>
